orca-sim
SingleCoreExt.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * This file is part of project ORCA. More information on the project
3  * can be found at the following repositories at GitHub's website.
4  *
5  * http://https://github.com/andersondomingues/orca-sim
6  * http://https://github.com/andersondomingues/orca-software
7  * http://https://github.com/andersondomingues/orca-mpsoc
8  * http://https://github.com/andersondomingues/orca-tools
9  *
10  * Copyright (C) 2018-2020 Anderson Domingues, <ti.andersondomingues@gmail.com>
11  *
12  * This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License along
23  * with this program; if not, write to the Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 ******************************************************************************/
26 // signal manip
27 #include <signal.h>
28 
29 #include <iostream>
30 #include <iomanip>
31 #include <chrono>
32 #include <cmath>
33 
34 // models
35 #include "Memory.hpp"
36 #include "HFRiscV.hpp"
37 #include "NetBridge.hpp"
38 #include "DmaNetif.hpp"
39 
40 // orca-specific hardware
41 #include "MemoryMap.h"
42 #include "SingleCoreExt.hpp"
43 
44 // simulation artifacts
45 #include "Event.hpp"
46 #include "Simulator.hpp"
47 
51 
52 SingleCoreExt::SingleCoreExt(int argc, char** argv): Simulator(argc, argv) {
53  if(argc != 2){
54  std::cout << "Usage: " << std::endl;
55  std::cout << "\t" << argv[0] << " <software image>" << std::endl;
56  }
57 }
58 
65  // instantiate signals (note that only signals that could be accessed
66  // through memory must have associated address)
67  signal_stall = new Signal<uint8_t>("sig.stall");
68  signal_intr = new Signal<uint8_t>("sig.intr");
69  signal_addr = new Signal<uint32_t>(SIGNAL_PROG_ADDR, "sig.prog-addr");
70  signal_size = new Signal<uint32_t>(SIGNAL_PROG_SIZE, "sig.prog-size");
71  signal_dist = new Signal<uint16_t>(SIGNAL_PROG_DEST, "sig.prog-dest");
72 
73  signal_recv_reload = new Signal<uint8_t>("sig.recv-reload");
74  signal_prog_send = new Signal<uint8_t>("sig.prog-send");
75  signal_prog_recv = new Signal<uint8_t>("sig.prog-recv");
76  signal_send_status = new Signal<uint8_t>("sig.send-status");
77  signal_recv_status = new Signal<uint32_t>("sig.recv-status");
78 
79  // instantiate modules
80  mem = new Memory("main-memory", ORCA_MEMORY_SIZE, ORCA_MEMORY_BASE);
81  cpu = new HFRiscV("cpu", signal_intr, signal_stall, mem);
82 
83  // map control signals to memory space so that software can access them
84  signal_addr->MapTo(mem->GetMap(SIGNAL_PROG_ADDR), SIGNAL_PROG_ADDR);
85  signal_size->MapTo(mem->GetMap(SIGNAL_PROG_SIZE), SIGNAL_PROG_SIZE);
86  signal_dist->MapTo(mem->GetMap(SIGNAL_PROG_DEST), SIGNAL_PROG_DEST);
87  signal_prog_send->MapTo(mem->GetMap(SIGNAL_PROG_SEND), SIGNAL_PROG_SEND);
88  signal_prog_recv->MapTo(mem->GetMap(SIGNAL_PROG_RECV), SIGNAL_PROG_RECV);
89 
90  // reset control wires
91  signal_stall->Write(0);
92  signal_intr->Write(0);
93  signal_addr->Write(0);
94  signal_size->Write(0);
95  signal_dist->Write(0);
96 
97  // create a dma and off-chip comm modules
98  bridge = new NetBridge("comm");
99  netif = new DmaNetif("dma");
100 
101  // connect the dma and netif to each other (via buffers)
104 
105  // connect netif to control wires
106  netif->SetSignalIntr(signal_intr);
108  netif->SetSignalProgAddr(signal_addr);
109  netif->SetSignalProgSize(signal_size);
110  netif->SetSignalProgDest(signal_dist);
111  netif->SetSignalRecvReload(signal_recv_reload);
112  netif->SetSignalProgSend(signal_prog_send);
113  netif->SetSignalProgRecv(signal_prog_recv);
114  netif->SetSignalRecvStatus(signal_recv_status);
115  netif->SetSignalSendStatus(signal_send_status);
116 
117  // create additional memory for send/recv processes
118  mem1 = new Memory("netif-mem-1", ORCA_MEMORY_SIZE_1, 0);
119  mem2 = new Memory("netif-mem-2", ORCA_MEMORY_SIZE_2, 0);
120 
121  // connect netif to memories
122  netif->SetMem0(mem);
123  netif->SetMem1(mem1);
124  netif->SetMem2(mem2);
125 
126  // map counters to memory if hardware counters were enabled
127  #ifdef MEMORY_ENABLE_COUNTERS
128  // map main memory counter
129  mem->GetSignalCounterStore()->MapTo(
130  mem->GetMap(M0_COUNTER_STORE_ADDR), M0_COUNTER_STORE_ADDR);
131  mem->GetSignalCounterLoad()->MapTo(
132  mem->GetMap(M0_COUNTER_LOAD_ADDR), M0_COUNTER_LOAD_ADDR);
133 
134  mem1->GetSignalCounterStore()->MapTo(
135  mem->GetMap(M1_COUNTER_STORE_ADDR), M1_COUNTER_STORE_ADDR);
136  mem1->GetSignalCounterLoad()->MapTo(
137  mem->GetMap(M1_COUNTER_LOAD_ADDR), M1_COUNTER_LOAD_ADDR);
138  mem2->GetSignalCounterStore()->MapTo(
139  mem->GetMap(M2_COUNTER_STORE_ADDR), M2_COUNTER_STORE_ADDR);
140  mem2->GetSignalCounterLoad()->MapTo(
141  mem->GetMap(M2_COUNTER_LOAD_ADDR), M2_COUNTER_LOAD_ADDR);
142  #endif
143 
144  #ifdef HFRISCV_ENABLE_COUNTERS
145  // memory mapping
146  cpu->GetSignalCounterArith()->MapTo(
147  mem->GetMap(CPU_COUNTER_ARITH_ADDR), CPU_COUNTER_ARITH_ADDR);
148  cpu->GetSignalCounterLogical()->MapTo(
149  mem->GetMap(CPU_COUNTER_LOGICAL_ADDR), CPU_COUNTER_LOGICAL_ADDR);
150  cpu->GetSignalCounterShift()->MapTo(
151  mem->GetMap(CPU_COUNTER_SHIFT_ADDR), CPU_COUNTER_SHIFT_ADDR);
152  cpu->GetSignalCounterBranches()->MapTo(
153  mem->GetMap(CPU_COUNTER_BRANCHES_ADDR), CPU_COUNTER_BRANCHES_ADDR);
154  cpu->GetSignalCounterJumps()->MapTo(
155  mem->GetMap(CPU_COUNTER_JUMPS_ADDR), CPU_COUNTER_JUMPS_ADDR);
156  cpu->GetSignalCounterLoadStore()->MapTo(
157  mem->GetMap(CPU_COUNTER_LOADSTORE_ADDR), CPU_COUNTER_LOADSTORE_ADDR);
158  cpu->GetSignalCounterCyclesTotal()->MapTo(
159  mem->GetMap(CPU_COUNTER_CYCLES_TOTAL_ADDR),
160  CPU_COUNTER_CYCLES_TOTAL_ADDR);
161  cpu->GetSignalCounterCyclesStall()->MapTo(
162  mem->GetMap(CPU_COUNTER_CYCLES_STALL_ADDR),
163  CPU_COUNTER_CYCLES_STALL_ADDR);
164  cpu->GetSignalHostTime()->MapTo(
165  mem->GetMap(CPU_COUNTER_HOSTTIME_ADDR), CPU_COUNTER_HOSTTIME_ADDR);
166  #endif
167 
168  // load software image into memory
169  mem->LoadBin(GetParam(1), ORCA_MEMORY_BASE, ORCA_MEMORY_SIZE);
170 }
171 
178  // schedule cpu
179  // cpu starts at the 3rd cycle due to its the first
180  // having one instruction coming out of the pipeline
181  Register(this->cpu, 3);
182  Register(this->bridge);
183  Register(this->netif);
184 }
185 
187  // minimal reporting
188  std::cout << "cpu: INTR=" << static_cast<int>(signal_intr->Read())
189  << ", STALL=" << static_cast<int>(signal_stall->Read())
190  << std::endl;
191 
192  // if counters enabled, report them
193  #ifdef HFRISCV_ENABLE_COUNTERS
194  std::cout << "cpu"
195  "\tiarith\t\t" << static_cast<int>(cpu->GetSignalCounterArith()->Read())
196  << std::endl <<
197  "\tilogic\t\t"
198  << static_cast<int>(cpu->GetSignalCounterLogical()->Read())
199  << std::endl <<
200  "\tishift\t\t" << static_cast<int>(cpu->GetSignalCounterShift()->Read())
201  << std::endl <<
202  "\tibranch\t\t"
203  << static_cast<int>(cpu->GetSignalCounterBranches()->Read())
204  << std::endl <<
205  "\tijumps\t\t" << static_cast<int>(cpu->GetSignalCounterJumps()->Read())
206  << std::endl <<
207  "\timemop\t\t"
208  << static_cast<int>(cpu->GetSignalCounterLoadStore()->Read())
209  << std::endl <<
210  "\ticycles\t\t"
211  << static_cast<int>(cpu->GetSignalCounterCyclesTotal()->Read())
212  << std::endl <<
213  "\tistalls\t\t"
214  << static_cast<int>(cpu->GetSignalCounterCyclesStall()->Read())
215  << std::endl <<
216  "\tihtime\t\t" << static_cast<int>(cpu->GetSignalHostTime()->Read())
217  << std::endl;
218 
219  #endif
220 
221  #ifdef MEMORY_ENABLE_COUNTERS
222  std::cout << "mem"
223  "\tloads\t\t" << static_cast<int>(mem->GetSignalCounterStore()->Read())
224  << std::endl <<
225  "\tstores\t\t" << static_cast<int>(mem->GetSignalCounterLoad()->Read())
226  << std::endl;
227  #endif
228 
229  SetExitStatus(0);
230 }
231 
233  // free resources
234  delete(cpu);
235  delete(mem);
236  delete(signal_intr);
237  delete(signal_stall); // missing signals here
238 
239  delete(mem1);
240  delete(mem2);
241  delete(netif);
242 }
243 
248 int main(int argc, char** argv) {
249  SingleCoreExt* simulator = new SingleCoreExt(argc, argv);
250  simulator->Simulate();
251  int ret = simulator->GetExitStatus();
252  return ret;
253 }
254 
255 
256 
The Signal class models a generic bus of width equals to the sizeof(T)
Definition: Signal.hpp:45
void SetSignalProgRecv(Signal< uint8_t > *)
Definition: DmaNetif.cpp:107
#define SIGNAL_PROG_RECV
Definition: _MemoryMap.h:21
void MapTo(bool keep_val=true)
Maps current Signal to the internal storage.
Definition: Signal.cpp:79
void SetSignalIntr(Signal< uint8_t > *)
Definition: DmaNetif.cpp:104
void SetOutputBuffer(Buffer< FlitType > *)
Definition: NetBridge.cpp:149
#define SIGNAL_PROG_DEST
Definition: MemoryMap.h:45
#define SIGNAL_PROG_SEND
Definition: _MemoryMap.h:20
#define SIGNAL_PROG_ADDR
Definition: _MemoryMap.h:24
void SetOutputBuffer(Buffer< FlitType > *ob)
Definition: DmaNetif.cpp:72
void SetSignalProgSend(Signal< uint8_t > *)
Definition: DmaNetif.cpp:106
T Read()
Get the last value writen to the bus.
Definition: Signal.cpp:118
void SetSignalRecvReload(Signal< uint8_t > *)
Definition: DmaNetif.cpp:108
Buffer< FlitType > * GetInputBuffer()
Definition: NetBridge.cpp:145
#define ORCA_MEMORY_SIZE_2
Definition: _MemoryMap.h:9
void SetSignalProgSize(Signal< uint32_t > *)
Definition: DmaNetif.cpp:112
void SetSignalRecvStatus(Signal< uint32_t > *)
Definition: DmaNetif.cpp:110
void Write(T val)
Writes some value to the bus.
Definition: Signal.cpp:127
#define SIGNAL_PROG_SIZE
Definition: _MemoryMap.h:25
void SetSignalProgDest(Signal< uint16_t > *)
Definition: DmaNetif.cpp:114
void Read(uint32_t addr, MemoryType *buffer, uint32_t length)
Reads data from a given memory location.
Definition: Memory.cpp:111
int main(int argc, char **argv)
This is the main routine for your application.
Buffer< FlitType > * GetInputBuffer()
Definition: DmaNetif.cpp:76
This class models a memory module.
Definition: Memory.hpp:55
void Schedule()
In this method, we add hardware models to the simulation queue.
#define ORCA_MEMORY_SIZE
Definition: MemoryMap.h:30
#define ORCA_MEMORY_BASE
Definition: MemoryMap.h:29
void SetSignalSendStatus(Signal< uint8_t > *)
Definition: DmaNetif.cpp:105
void Startup()
This routine regards the instantiation of hardware for the simulation.
void SetExitStatus(int status)
Definition: Simulator.cpp:143
std::string GetParam(int index)
Definition: Simulator.cpp:70
#define ORCA_MEMORY_SIZE_1
Definition: _MemoryMap.h:7
void SetSignalStall(Signal< uint8_t > *)
Definition: DmaNetif.cpp:103
void Register(TimedModel *m)
Definition: Simulator.cpp:99
void SetSignalProgAddr(Signal< uint32_t > *)
Definition: DmaNetif.cpp:111