...
 
Commits (1)
......@@ -25,7 +25,30 @@ using namespace TRC;
/* Wires bodies */
Wires Wires::operator&&(const Wires &w) const // MIN
bool Wires::operator==(const Wires &w) const
{
int n = size();
if(n != w.size()) return false;
for(int i=0;i<n;i++)
{
char c1 = s[i];
char c2 = w.get(i);
if(c1==ANYBIT || c1==ANYTRIT || c2==ANYBIT || c2==ANYTRIT)
{
if(c1==ANYBIT && c2!=TRUE && c2!=FALSE && c2!=PULLUP && c2!=PULLDOWN) return false;
if(c1==ANYTRIT && c2!=TRUE && c2!=MAYBE && c2!=FALSE && c2!=PULLUP && c2!=PULLMID && c2!=PULLDOWN) return false;
if(c2==ANYBIT && c1!=TRUE && c1!=FALSE && c1!=PULLUP && c1!=PULLDOWN) return false;
if(c2==ANYTRIT && c1!=TRUE && c1!=MAYBE && c1!=FALSE && c1!=PULLUP && c1!=PULLMID && c1!=PULLDOWN) return false;
}
else if((c1==TRUE || c1==PULLUP) && c2!=TRUE && c2!=PULLUP) return false;
else if((c1==MAYBE || c1==PULLMID) && c2!=MAYBE && c2!=PULLMID) return false;
else if((c1==FALSE || c1==PULLDOWN) && c2!=FALSE && c2!=PULLDOWN) return false;
else if(c1!=c2) return false;
}
return true;
}
Wires Wires::min(const Wires &w) const
{
int n = size();
int m = w.size();
......@@ -105,7 +128,7 @@ Wires Wires::operator&&(const Wires &w) const // MIN
return r;
}
Wires Wires::operator||(const Wires &w) const // MAX
Wires Wires::max(const Wires &w) const
{
int n = size();
int m = w.size();
......@@ -185,7 +208,7 @@ Wires Wires::operator||(const Wires &w) const // MAX
return r;
}
Wires Wires::operator~() const /* INV */
Wires Wires::inv() const
{
int n = size();
Wires r(n,type());
......
......@@ -92,14 +92,18 @@ namespace TRC
int t;
char *s;
Wires(unsigned short n, int b = UNSPECIFIED)
Wires(unsigned short n, int b = UNSPECIFIED, char c = NC)
{
t = b + n;
s = new char[n+1];
for(int i=0;i<n;i++) s[i]=NC;
for(int i=0;i<n;i++) s[i]=c;
s[n] = 0;
}
Wires min(const Wires &w) const;
Wires max(const Wires &w) const;
Wires inv() const;
public:
virtual ~Wires()
......@@ -197,6 +201,16 @@ namespace TRC
return ss;
}
Wires part(int from, int to)
{
int n = size();
if(from<0 || from>n || to<0 || to>n || to<from) throw RuntimeException("Wires.part() - out of range");;
int sz = to+1-from;
Wires w(sz,type());
for(int i=0;i<sz;i++) w[i]=s[from+i];
return w;
}
char & operator[](int i)
{
if(i<0 || i>=size()) throw RuntimeException("Wires[] - out of range");;
......@@ -209,6 +223,8 @@ namespace TRC
return s[i];
}
Wires operator~() const { return inv(); }
Wires & operator=(const Wires &w)
{
if(this != &w)
......@@ -220,26 +236,22 @@ namespace TRC
return *this;
}
bool operator==(const Wires &w) const
{
int n = size();
if(n != w.size()) return false;
for(int i=0;i<n;i++) if(s[i]!=w.get(i)) return false;
return true;
}
bool operator==(const Wires &w) const;
bool operator==(char c) const
{
int n = size();
for(int i=0;i<n;i++) if(s[i]!=c) return false;
return true;
}
bool operator!=(const Wires &w) const { return !(*this==w); }
bool operator==(char c) const { Wires w(size(),type(),c); return (*this==w); }
bool operator!=(char c) const { Wires w(size(),type(),c); return (*this!=w); }
operator bool() const { return !(*this==FALSE); }
Wires operator&&(const Wires &w) const;
Wires operator||(const Wires &w) const;
Wires operator~() const;
};
inline std::ostream & operator<<(std::ostream &o, const Wires &w)
{
o << w.reverse();
return o;
}
// class Wire<N> (N wires)
template<unsigned short N> class Wire : public Wires
......@@ -287,13 +299,10 @@ namespace TRC
for(int i=0;i<N;i++) s[i] = c;
return *this;
}
};
template<unsigned short N> std::ostream & operator<<(std::ostream &o, const Wire<N> &w)
{
o << w.reverse();
return o;
}
Wire<N> operator&(const Wires &w) const { return min(w); }
Wire<N> operator|(const Wires &w) const { return max(w); }
};
// class Uint<N> (unsigned N-bit integer)
......@@ -351,6 +360,54 @@ namespace TRC
}
return i;
}
bool operator==(const Uint<N> w)
{
unsigned a = (unsigned)(*this);
unsigned b = (unsigned)w;
return (a==b);
}
bool operator==(unsigned b)
{
unsigned a = (unsigned)(*this);
return (a==b);
}
bool operator>(const Uint<N> w)
{
unsigned a = (unsigned)(*this);
unsigned b = (unsigned)w;
return (a>b);
}
bool operator>(unsigned b)
{
unsigned a = (unsigned)(*this);
return (a>b);
}
bool operator<(const Uint<N> w)
{
unsigned a = (unsigned)(*this);
unsigned b = (unsigned)w;
return (a<b);
}
bool operator<(unsigned b)
{
unsigned a = (unsigned)(*this);
return (a<b);
}
bool operator!=(const Uint<N> w) { return !((*this)==w); }
bool operator!=(unsigned b) { return !((*this)==b); }
bool operator<=(const Uint<N> w) { return !((*this)>w); }
bool operator<=(unsigned b) { return !((*this)>b); }
bool operator>=(const Uint<N> w) { return !((*this)<w); }
bool operator>=(unsigned b) { return !((*this)<b); }
};
template<unsigned short N> std::ostream & operator<<(std::ostream &o, const Uint<N> &w)
......@@ -425,6 +482,52 @@ namespace TRC
}
return (int)i;
}
bool operator==(const Sint<N> w)
{
int a = (int)(*this);
int b = (int)w;
return (a==b);
}
bool operator==(int b)
{
int a = (int)(*this);
return (a==b);
}
bool operator>(const Sint<N> w)
{
int a = (int)(*this);
int b = (int)w;
return (a>b);
}
bool operator>(int b)
{
int a = (int)(*this);
return (a>b);
}
bool operator<(const Sint<N> w)
{
int a = (int)(*this);
int b = (int)w;
return (a<b);
}
bool operator<(int b)
{
int a = (int)(*this);
return (a<b);
}
bool operator!=(const Sint<N> w) { return !((*this)==w); }
bool operator!=(int b) { return !((*this)==b); }
bool operator<=(const Sint<N> w) { return !((*this)>w); }
bool operator<=(int b) { return !((*this)>b); }
bool operator>=(const Sint<N> w) { return !((*this)<w); }
bool operator>=(int b) { return !((*this)<b); }
};
template<unsigned short N> std::ostream & operator<<(std::ostream &o, const Sint<N> &w)
......@@ -472,17 +575,44 @@ namespace TRC
inline Signal operator&(const Signal &a, const Signal &b)
{
return a && b;
Signal f = FALSE;
if((bool)a) return b;
return f;
}
inline Signal operator&(bool a, const Signal &b)
{
Signal f = FALSE;
if(a) return b;
return f;
}
inline Signal operator&(const Signal &a, bool b)
{
Signal f = FALSE;
if(b) return a;
return f;
}
inline Signal operator|(const Signal &a, const Signal &b)
{
return a || b;
Signal f = TRUE;
if((bool)a) return f;
else b;
}
inline Signal operator|(bool a, const Signal &b)
{
Signal f = TRUE;
if(a) return f;
return b;
}
inline Signal operator!(const Signal &a)
inline Signal operator|(const Signal &a, bool b)
{
return ~a;
Signal f = TRUE;
if(b) return f;
return a;
}
// Simulation classes:
......
// OPC1 test - based on https://github.com/revaldinho/opc/tree/master/opc1
#include <TRCMath.hpp>
using namespace std;
using namespace TRC;
// module opccpu( inout[7:0] data, output[10:0] address, output rnw, input clk, input reset_b); // SEE BELOW
class OPC1 : public Entity
{
public:
// parameter FETCH0=0, FETCH1=1, RDMEM=2, RDMEM2=3, EXEC=4 ;
const unsigned FETCH0=0, FETCH1=1, RDMEM=2, RDMEM2=3, EXEC=4;
// parameter AND=5'bx0000, LDA=5'bx0001, NOT=5'bx0010, ADD=5'bx0011;
const Wire<5> AND, LDA, NOT, ADD; // SEE BELOW
// parameter LDAP=5'b01001, STA=5'b11000, STAP=5'b01000;
const Wire<5> LDAP, STA, STAP; // SEE BELOW
// parameter JPC=5'b11001, JPZ=5'b11010, JP=5'b11011, JSR=5'b11100;
const Wire<5> JPC, JPZ, JP, JSR; // SEE BELOW
// parameter RTS=5'b11101, LXA=5'b11110;
const Wire<5> RTS, LXA; // SEE BELOW
// reg [10:0] OR_q, PC_q;
Wire<11> OR_q;
Uint<11> PC_q;
// reg [7:0] ACC_q;
Uint<8> ACC_q;
// reg [2:0] FSM_q;
Uint<3> FSM_q;
// reg [4:0] IR_q;
Wire<5> IR_q;
// reg [2:0] LINK_q; // bottom bit doubles up as carry flag
Wire<3> LINK_q;
//`define CARRY LINK_q[0]
#define CARRY LINK_q[0]
// IMPLEMENTATION OF INTERFACE (inout[7:0] data, output[10:0] address, output rnw, input clk, input reset_b);
int i_data, i_address, i_rnw, i_clk, i_reset_b;
OPC1() : Entity("OPC1"),
// initialization for constant Wire<5>s:
AND("X0000"), LDA("X0001"), NOT("X0010"), ADD("X0011"),
LDAP("01001"), STA("11000"), STAP("01000"),
JPC("11001"), JPZ("11010"), JP("11011"), JSR("11100"),
RTS("11101"), LXA("11110")
{
// global attachements (we have the only instance of the class so it will work)
i_data = at("DATA",8,PULLUP);
i_address = at("ADDRESS",11);
i_rnw = at("RNW");
i_clk = at("CLK");
i_reset_b = at("RESET_B");
}
void step()
{
Signal reset_b = io(i_reset_b).read();
// wire writeback_w = ((FSM_q == EXEC) && (IR_q == STA || IR_q == STAP)) & reset_b ;
Signal writeback_w = ((FSM_q == EXEC) && (IR_q == STA || IR_q == STAP)) & reset_b ;
// assign rnw = ~writeback_w ;
Signal rnw = ~writeback_w;
// assign data = (writeback_w)?ACC_q:8'bz ;
Wire<8> data; // it's all Z by default
if(writeback_w) data = ACC_q;
else // below required for later logic
{
for(int i=0;i<8;i++) data[i] = io(i_data+i).read();
}
// assign address = ( writeback_w || FSM_q == RDMEM || FSM_q==RDMEM2)? OR_q:PC_q;
Wire<11> address = ( (bool)writeback_w || FSM_q == RDMEM || FSM_q==RDMEM2 )? OR_q:PC_q;
// always @ (posedge clk or negedge reset_b )
if(posedge(i_clk) || negedge(i_reset_b))
{
// if (!reset_b)
if (!reset_b)
// FSM_q <= FETCH0;
FSM_q = FETCH0;
// else
else
{
// case(FSM_q)
// FETCH0 : FSM_q <= FETCH1;
if(FSM_q == FETCH0) FSM_q = FETCH1;
// FETCH1 : FSM_q <= (IR_q[4])?EXEC:RDMEM ;
else if(FSM_q == FETCH1) FSM_q = (IR_q[4]==TRUE)?EXEC:RDMEM;
// RDMEM : FSM_q <= (IR_q==LDAP)?RDMEM2:EXEC;
else if(FSM_q == RDMEM) FSM_q = (IR_q==LDAP)?RDMEM2:EXEC;
// RDMEM2 : FSM_q <= EXEC;
else if(FSM_q == RDMEM2) FSM_q = EXEC;
// EXEC : FSM_q <= FETCH0;
else if(FSM_q == EXEC) FSM_q = FETCH0;
// endcase
}
}
// always @ (posedge clk)
if(posedge(i_clk))
// begin
{
// IR_q <= (FSM_q == FETCH0)? data[7:3] : IR_q;
if(FSM_q == FETCH0)
{
IR_q[0] = data[3];
IR_q[1] = data[4];
IR_q[2] = data[5];
IR_q[3] = data[6];
IR_q[4] = data[7];
}
// // OR_q[10:8] is upper part nybble for address - needs to be zeroed
// // for both pointer READ and WRITE operations once ptr val is read
// OR_q[10:8] <= (FSM_q == FETCH0)? data[2:0]: (FSM_q==RDMEM)?3'b0:OR_q[10:8];
if(FSM_q == FETCH0)
{
OR_q[8] = data[0];
OR_q[9] = data[1];
OR_q[10] = data[2];
}
else if(FSM_q == RDMEM)
{
OR_q[8] = FALSE;
OR_q[9] = FALSE;
OR_q[10] = FALSE;
}
// OR_q[7:0] <= data; //Lowest byte of OR is dont care in FETCH0 and at end of EXEC
for(int i=0;i<8;i++) OR_q[i] = data[i];
// if ( FSM_q == EXEC )
if(FSM_q == EXEC)
{
// casex (IR_q)
// JSR : {LINK_q,ACC_q} <= PC_q ;
if(IR_q==JSR)
{
LINK_q = PC_q.part(8,10);
ACC_q = PC_q.part(0,7);
}
// LXA : {LINK_q,ACC_q} <= {ACC_q[2:0], 5'b0, LINK_q};
else if(IR_q==LXA)
{
LINK_q = ACC_q.part(0,2);
for(int i=7;i>=0;i--)
{
if(i>=3) ACC_q[i] = FALSE;
else ACC_q[i] = LINK_q[i];
}
}
// AND : {`CARRY, ACC_q} <= {1'b0, ACC_q & OR_q[7:0]};
else if(IR_q==AND)
{
CARRY = FALSE;
ACC_q = ACC_q & OR_q.part(0,7);
}
// NOT : ACC_q <= ~OR_q[7:0];
else if(IR_q==NOT)
{
ACC_q = ~OR_q.part(0,7);
}
// LDA : ACC_q <= OR_q[7:0];
else if(IR_q==LDA)
{
ACC_q = OR_q.part(0,7);
}
// LDAP : ACC_q <= OR_q[7:0];
else if(IR_q==LDAP)
{
ACC_q = OR_q.part(0,7);
}
// ADD : {`CARRY,ACC_q} <= ACC_q + `CARRY + OR_q[7:0];
else if(IR_q==ADD)
{
ACC_q += OR_q.part(0,7);
if(CARRY==TRUE) ACC_q++;
if(ACC_q.overflow())
CARRY = TRUE;
else CARRY = FALSE;
}
// default: {`CARRY,ACC_q} <= {`CARRY,ACC_q};
// endcase
}
// end
}
// always @ (posedge clk or negedge reset_b )
if(posedge(i_clk) || negedge(i_reset_b))
{
// if (!reset_b) // On reset start execution at 0x100 to leave page zero clear for variables
if(!reset_b)
// PC_q <= 11'h100;
PC_q = 0x100;
// else
else
// if ( FSM_q == FETCH0 || FSM_q == FETCH1 )
if(FSM_q==FETCH0 || FSM_q==FETCH1)
// PC_q <= PC_q + 1;
PC_q++;
// else
else
{
// case (IR_q)
// JP : PC_q <= OR_q;
if(IR_q==JP)
{
PC_q = OR_q;
}
// JPC : PC_q <= (`CARRY)?OR_q:PC_q;
else if(IR_q==JPC)
{
PC_q = (CARRY==TRUE)?OR_q:PC_q;
}
// JPZ : PC_q <= ~(|ACC_q)?OR_q:PC_q;
else if(IR_q==JPZ)
{
PC_q = (ACC_q==0)?OR_q:PC_q;
}
// JSR : PC_q <= OR_q;
else if(IR_q==JSR)
{
PC_q = OR_q;
}
// RTS : PC_q <= {LINK_q, ACC_q};
else if(IR_q==RTS)
{
for(int i=10;i>=0;i--)
{
if(i>=8) PC_q[i]=LINK_q[i-8];
else PC_q[i]=ACC_q[i];
}
}
// default: PC_q <= PC_q;
// endcase
}
if(writeback_w)
{
for(int i=0;i<8;i++) io(i_data) << data[i];
}
for(int i=0;i<11;i++) io(i_address) << address[i];
io(i_rnw) << rnw;
}
//endmodule
}
};
......@@ -65,14 +65,14 @@ class MyUnit : public Entity
int main()
{
Wire<5> a = "11111";
Wire<5> a("11111");
Wire<32> b = FALSE;
Wire<1> signal,out;
Signal signal2;
Sint<32> s = 0;
s[31] = TRUE;
b[0] = TRUE;
Uint<32> u = b || s;
Uint<32> u = b | s;
Sint<5> small = -16;
signal = MAYBE;
signal2 = TRUE;
......@@ -85,6 +85,9 @@ int main()
cout << "b=" << b << endl;
cout << "s=" << s << endl;
cout << "u=" << u << endl;
cout << "b.part(0,2)=" << b.part(0,2).binarize() << endl;
if(b && s) cout << "true" << endl;
else cout << "false" << endl;
System *sys = System::getInstance();
class Unit1 : public MyUnit
......