Académique Documents
Professionnel Documents
Culture Documents
5Z032
SystemC + miniMIPS
Henk Corporaal
Eindhoven University of Technology
2011
1
Hardware-software co-design
Were designing a processor system.
This is hardware that runs software.
We need to design BOTH hardware and software
Hence the name:
Hardware-Software co-design.
In our case the hardware is an FPGA. In real life this
could be a multi-million dollar chip that takes 6 months to
implement in hardware.
We need to emulate/simulate the hardware before were
actually making it. In this way errors can be found early
on.
A simulation model of the hardware can be described in
SystemC. This is actually a C++ program with a special
toolkit.
We also compile our SystemC processor into FPGA
hardware; so we use SystemC for 2 purposes.
Hardware
System
Software
C++ compiler
Analyze:
waveform, etc
subset
of MIPS
instructions
lcc.exe
C compiler
mips-as.exe
MIPS assembler
Synopsys
CoCentric compiler
FPGA hardware:
Your MIPS
machine
processor
code
system
(program)
machine
code
(program)
ram
Analyze: Oscilloscope,
logic analyzer, etc.
C-program
file.c
runs in cygwin
Programming flow
MIPS simulator
spim.exe
Compiler
lcc.exe
software
MIPS
assembler
file.asm
MIPS
assembler
Assembler
mips-as.exe
Initially we
start here
To strip the
first 34 bytes
Disassembler
disas
Object code
file.o
hardware
runs in Windows
SystemC model
of miniminiMIPS
C++ source
main.cpp
C++ source
main.cpp
C++ source
C++ source
main.cpp
main.cpp
C++ compiler
Visual C++
Model of mips
single-cycle.exe
Simulation output
mips.vcd
cygwin
Some of the programs we use (LCC, the MIPS assembler) are written
as UNIX tools.
The distribution contains a GNU Unix environment called cygwin.
SystemC
SystemC is a C++ library with class definitions.
You write some C++ code using the classes. This
describes two issues:
1 Circuit structure (schematic/functionality)
2 Simulation settings
Compiling and running it will perform the simulation.
SystemC is just C++ code, though it looks funny.
User
User
Module
Module
#2
#2
.....
User
User
Module
Module
#N
#N
SystemC
SystemC
Executable Specification
Executable Specification
void main(void) {
double p = 10.0, q = 12.0;
int r = 15, s = 1;
void main(void) {
double p = 10.0, q = 12.0;
int r = 15, s = 1;
double a = maximum(p, q);
int b = maximum(r, s);
}
Behind the scenes, the compiler builds the routine for each class that is required.
This is a little heavy on the compiler, and also harder to debug.
void main(void) {
coordinate <int> a(1, 2);
coordinate <double> b(3.2, 6.4);
a.print();
b.print();
}
1 , 2
3.2 , 6.4
Again, the compiler builds a separate code instance for each type
that is required.
void main(void) {
sc_signal< sc_bv<32> > bus_mux1;
}
Signal wires
32 bit vector
OR
#include <systemc.h>
SC_MODULE(OR2)
{
sc_in<bool> a;
sc_in<bool> b;
// input pin a
// input pin b
void or_process() {
o.write( a.read() || b.read() );
}
};
Instantiates the
input pins a and b.
They carry boolean
sygnals.
This object inherits all
systemC properties
of a pin. how this is
actually implemented
is hidden from us!
Similarly, a boolean
output pin called o
Tells the simulator
which function to
run to evaluate the
output pin
Run the method when
signal a or b changes
This is the actual or!
INV9
AND4
AND5
OR2
OR8
AND6
Module type
Instance name
in instance
or_1
and_3
nor_7
AND3
NOR7
AND4
OR2
A
B
CI
Boolean
signal
or_2
AND5
INV9
and_4
and_5
OR8
AND6
CO
and_6
SUM
Template class
used for boolean
or_1
and_3
AND3
NOR7
AND4
OR2
A
B
CI
or_2
AND5
CO
nor_7
and_4
and_5
OR8
AND6
INV9
and_6
SUM
; i++ )
0);
0);
0);
//
//
//
//
sc_close_vcd_trace_file(tf);
}
Waveform viewer
Modules
Modules are the basic building blocks to partition a design
they allow to partition complex systems in smaller components
Modules hide internal data representation, use interfaces
Modules are classes in C++
A module is similar to an entity in VHDL
SC_MODULE(module_name)
{
// Ports declaration
// Signals declaration
// Module constructor : SC_CTOR
// Process constructors and sensibility list
//
SC_METHOD
// Sub-Modules creation and port mappings
// Signals initialization
}
in1
out
in2
in1;
in2;
selection;
out;
MUX
SC_CTOR( Mux21 ) {
SC_METHOD( doIt );
sensitive << selection;
sensitive << in1;
sensitive << in2;
selection
}
};
Example: 'filter'
3 types of Processes
Methods
When activated, executes and returns (just like a function)
SC_METHOD(process_name);
SC_THREAD(process_name);
CThreads
Activated by the clock pulse
SC_CTHREAD(process_name, clock value);
An Example of an SC_THREAD
void do_count() {
while(1) {
if(reset) {
value = 0;
}
else if (count) {
value++;
q.write(value);
}
wait();
}
}
Repeat forever
SC_THREAD Example
SC_MODULE(my_module)
{
sc_in<bool> id;
sc_in<bool> clock;
sc_in<sc_uint<3> > in_a;
sc_in<sc_uint<3> > in_b;
sc_out<sc_uint<3> > out_c;
void my_thread();
SC_CTOR(my_module)
{
SC_THREAD(my_thread);
sensitive << clock.pos();
}
};
Thread implementation:
//my_module.cpp
void my_module:: my_thread()
{
while(true)
{
if (id.read())
out_c.write(in_a.read());
else
out_c.write(in_b.read());
wait();
}
};
SC_CTHREAD
Will be deprecated in future releases
Almost identical to SC_THREAD, but implements
clocked threads
Sensitive only to one edge of one and only one clock
It is not triggered if inputs other than the clock change
Models the behavior of unregistered inputs and registered
outputs
Useful for high level simulations, where the clock is used as
the only synchronization device
Adds wait_until( ) and watching( ) semantics for easy
deployment
Counter in SystemC
SC_MODULE(countsub)
{
sc_in<double> in1;
sc_in<double> in2;
sc_out<double> sum;
sc_out<double> diff;
sc_in<bool>
clk;
void addsub();
// Constructor:
SC_CTOR(countsub)
{
// Declare addsub as SC_METHOD
SC_METHOD(addsub);
// make it sensitive to
// positive clock
sensitive_pos << clk;
}
};
in1
in2
clk
sum
adder
subtractor
diff
How to declare
IN :
OUT :
Bi-Directional :
sc_in<port_typ>
sc_out<port_type>
sc_inout<port_type>
Examples:
in_tmp = in.read( );
out.write(out_temp);
Clocks
Special object
How to create ?
sc_clock clock_name (
clock_label, period, duty_ratio, offset, initial_value );
Clock connection
sc_clock
sc_clockclock1
clock1("clock1",
("clock1",20,
20,0.5,
0.5,2,
2,true);
true);
22
12
12
22
22
32
32
42
42
Data Types
SystemC supports:
all C/C++ native types
plus specific SystemC types
SystemC types
Types for systems modelling
2 values (0,1)
4 values (0,1,Z,X)
Arbitrary size integer (Signed/Unsigned)
Fixed point types
SC_LOGIC type
More general than bool, 4 values :
(0 (false), 1 (true), X (undefined) , Z(high-impedance) )
Assignment like bool
my_logic = 0;
my_logic = Z;
Simulation time bigger than bool
Operators like bool
Declaration
sc_logic my_logic;
Description
sc_logic
sc_int
sc_uint
sc_bigint
sc_biguint
sc_bv
sc_lv
sc_fixed
sc_ufixed
sc_fix
sc_ufix
sum
half-adder
carry
SC_MODULE (full_adder) {
sc_in<bool>a, b, carry_in;
sc_out<bool>sum, carry_out;
half-adder ha1
b
carry
carry_in
sum
sum
sum
half-adder ha2
b
carry
#Include full_adder.h
#Include pattern_gen.h
#include monitor.h
int sc_main(int argc, char* argv[]) {
sc_signal<booL> t_a, t_b, t_cin, t_sum,
t_cout;
full_adder f1(Fulladder);
//connect using positional association
f1 << t_a << t_b << t_cin << t_sum << t_cout;
pattern_gen pg_ptr = new
pattern_gen(Generation);
//connection using named association
pg_ptr->d_a(t_a);
pg_ptr->d_b(t_b);
(*pg_ptr->d_cin(t_cin);
monitor mol(Monitor);
mo1 << t_a << t_b << t_cin << t_sum << t_cout;
sc_start(100, SC_NS);
return 0;
}
Full_adder
Monitor
carry
c_in
Pattern_gen