TRCM - симулируем цифровое железо на C++

Использование и разработка софта (преимущественно на ПЦ)

Moderator: Shaos

User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

TRCM - симулируем цифровое железо на C++

Post by Shaos »

Нечто сподвигло меня вчера засесть за современный C++ и начать под лицензией GPLv3 писать систему симуляции, которая в перспективе могла бы быть пригодна служить в качестве HDL на замену всех этих ваших Вэрилогов :roll:

https://gitlab.com/ternary/trcm

Прожэкт на Хакадее: https://hackaday.io/project/160393-trcm
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Короче - до этого момента я всегда все свои симуляшные движки писал отталкиваясь от идеи, что у нас есть входы и есть выходы, но в реальности всё не так - источники напряжений могут подключаться и отключаться от проводников (двунаправленные сигналы) - тот же FPGA например невозможно сэмулировать не имея возможности переподключаться то так, то эдак. Вобщем я решил идти от уже проверенных промышленных подходов (добавив немного своего троичного) - на проводник могут накладываться вот такие значения:

Code: Select all

 // Wire states:
 const char TRUE     = 'P'; // прямое подключение к питанию
 const char MAYBE    = 'O'; // третье промежуточное состояние (для симуляции троичных схем)
 const char FALSE    = 'N'; // прямое подключение к земле
 const char ANYBIT   = 'X'; // любое двоичное значение для сравнений
 const char ANYTRIT  = 'Y'; // любое троичное значение для сравнений
 const char NC       = 'Z'; // не подключено (высокий импенданс)
 const char PULLUP   = '1'; // слабая подтяжка к питанию
 const char PULLDOWN = '0'; // слабая подтяжка к земле
 const char PULLMID  = '-'; // слабая подтяжка к среднему значению
 const char INVALID  = '?'; // ошибка (конфликт)

 // Aliases:
 const char HIGHIMP  = NC;
 const char POSITIVE = TRUE;
 const char NEUTRAL  = MAYBE;
 const char NEGATIVE = FALSE;
Например на NC может наложиться PULLUP, на который может наложится скажем FALSE, а вот если на проводнике был FALSE, то при попытке применить к нему TRUE результирующее состояние получится INVALID

P.S. 18 августа 2018 добавил "любое двоичное значение" X и "любое троичное значение" Y, а также подтяжку к среднему значению '-' (PULLMID)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Пример играния с шинами (C++ имеет возможность шаблонить классы цифрами):

Code: Select all

#include "TRCMath.hpp"

using namespace std;

using namespace TRC;

int main()
{
  Wire<5> a;
  Wire<32> b; 
  Wire<1> signal,out;
  Signal signal2;
  Uint<32> u;
  Sint<32> s;
  s[0] = TRUE;
  b[31] = FALSE;
  s = b&&u;
  signal = MAYBE;
  signal2 = TRUE;
  out = signal & signal2;
  cout << "signal=" << signal << endl;
  cout << "signal2=" << signal2 << endl;
  cout << "out=" << out << endl;
  cout << "a=" << a << endl;
  cout << "b=" << b << endl;
  cout << "u=" << u << endl;
  cout << "s=" << s << endl;
}
Пока есть только оператор && для шин и & для отдельных сигналов (Signal это просто другое название для Wire<1>) - позже добавлю все остальные логические и арифметические операции для работы с числами произвольной длины в битах и тритах (плюс будут типы данных с фиксированной и плавающей точкой - в частности эта либа покроет функционал вот этой моей недоделки).

Чтобы посимулить автоматы пользователь должен создать независимые модули в виде классов, которые наследуются от класса Entity, и определить им конструктор для инициализации и метод run() для прохода шага симуляции (может тогда этот метод переименовать в step?):

Code: Select all

class Unit1 : public Entity
{
 protected:

  // индексы:
  int i0,i1,i2;
  // входы (например):
  Wire<8> net;
  Uint<8> bus;
  // выходы (например):
  Signal sig;

 public:

  Unit1()
  {
    // цепляемся к глобальным сигналам по именам
    i0 = at("bus",8,PULLUP);
    i1 = at("network",8);
    i2 = at("single");
  }

  void run() // переименовать в step()?
  {
    // читаем наши входы
    for(int i=0;i<8;i++)
      bus[i] = io(i0+i).read();
    for(int i=0;i<8;i++)
      net[i] = io(i1+i).read();
    // чего-то делаем
    sig[0] = TRUE;
    // применяем обратно наши выходы
    io(i0) << sig[0];
    io(i0+1) << sig[0];
    io(i2) << sig[0];
    // триггерная логика "аля Вэрилог":
    if(posedge(i1+5))
    {
       // сюда попадаем если был положительный фронт на глобальном сигнале network[5]
    }
  }
};
Входы и выходы обозначены чисто формально - по ходу программы их назначение может меняться и одна и таже внешняя цепь в разное время может использваться и как вход, и как выход

В перспективе хочу добавить возможность отпочковывать методы run в треды, чтобы симуляция юзала многокоровые процы по максимуму (современный C++ поддерживает многопоточность на уровне самого языка, точнее на уровне STL)

P.S. Можно попробовать написать конвертер из верилога в такое представление на сях++, чтобы погонять существующие большие мягкие процы...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16689
Joined: 21 Oct 2009 08:08
Location: Россия

Re: TRCM - симулируем цифровое железо на C++

Post by Lavr »

Shaos wrote:Вобщем я решил идти от уже проверенных промышленных подходов (добавив немного своего троичного) - на проводник могут накладываться вот такие значения:

Code: Select all

 const char TRUE     = 'P'; // прямое подключение к питанию
 const char MAYBE    = 'O'; // третье промежуточное состояние (для симуляции троичных схем)
 const char FALSE    = 'N'; // прямое подключение к земле
 const char NC       = 'Z'; // не подключено (высокий импенданс)
 const char PULLUP   = '1'; // слабая подтяжка к питанию
 const char PULLDOWN = '0'; // слабая подтяжка к земпле
 const char INVALID  = 'X'; // ошибка (конфликт)
Ну надо же! :o А я знаю здесь не форуме одного человека, который называл это всё "грязными хаками"! :roll:
Тебе сказать, кто это, или сам догадаешься? :wink:
iLavr
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Ну таки хаки, только без них FPGA не сымитируешь ;)

P.S. Заменил X на ? и переименовал run() в step()
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16689
Joined: 21 Oct 2009 08:08
Location: Россия

Re: TRCM - симулируем цифровое железо на C++

Post by Lavr »

Shaos wrote:Ну таки хаки, только без них FPGA не сымитируешь ;)
Без них ты и троичную логику не сымитируешь ;) Но ты ведь так упирался! :roll:
viewtopic.php?p=140444#p140444

Кстати, " ? " , на мой взгляд, будет сбивать с толку. Лучше подбери подходящую букву.
iLavr
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Lavr wrote:
Shaos wrote:Ну таки хаки, только без них FPGA не сымитируешь ;)
Без них ты и троичную логику не сымитируешь ;) Но ты ведь так упирался! :roll:
viewtopic.php?p=140444#p140444
Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Lavr
Supreme God
Posts: 16689
Joined: 21 Oct 2009 08:08
Location: Россия

Re: TRCM - симулируем цифровое железо на C++

Post by Lavr »

Shaos wrote:
Lavr wrote:Без них ты и троичную логику не сымитируешь ;)
Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)
Железно ли, бетОнно ли, но одними лог. "0" и "1" - не обойтись. :lol:
Придётся так или иначе вводить лог. "1/2" , несмотря на то, что "входы есть входы, выходы есть выходы".

О чем, тебе, собственно, и говорили: viewtopic.php?p=140424#p140424
iLavr
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Lavr wrote:
Shaos wrote:
Lavr wrote:Без них ты и троичную логику не сымитируешь ;)
Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)
Железно ли, бетОнно ли, но одними лог. "0" и "1" - не обойтись. :lol:
Придётся так или иначе вводить лог. "1/2" , несмотря на то, что "входы есть входы, выходы есть выходы".
Да я собственно свой DDT имел ввиду - там только 3 значения N,O,P и никаких «грязных хаков» :)
Ну и плюс X при задании таблиц истинности...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

По существу есть претензии? Вопросы?

Я вот думаю что наверное надо спрятать от юзера чтение снаружи и запись вовне - скажем неявно это делать для железобетонных входов и железобетонных выходов (а такие точно будут).
А "входовыходы" менять по ходу работы (подключая их то как вход, то как выход, то как отключено) плюс наверное надо завести понятие "выход с Z состоянием", а также входы подтянутые к земле или к питанию.
Специальные OK выходы наверное заводить не стоит, хотя что такое OK? Это выход который может либо отключаться либо подключаться к земле, а на той стороне стоит подтяжка к питанию - так что это можно сымитировать уже имеющимися средствами...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Shaos wrote:Я вот думаю что наверное надо спрятать от юзера чтение снаружи и запись вовне - скажем неявно это делать для железобетонных входов и железобетонных выходов (а такие точно будут).
С другой стороны когда всё навиду, то всё прозрачно, вот так например можно Z-состояние делать:

Code: Select all

if(enabled)
  io(network1)<<store;
else
  io(network1)<<NC;
И входы можно читать не все всегда, а только те, которые нужны в текущем состоянии и т.д.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Lavr wrote:Кстати, " ? " , на мой взгляд, будет сбивать с толку. Лучше подбери подходящую букву.
Ну 0 и 1 тоже уже не буквы :)
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Есть момент, о котором я забыл - надо сделать так, чтобы было достаточно просто добавлять вложенные модули как члены класса!
Вложенный модуль не будет иметь доступ к внешним цепям, но будет иметь доступ ко внутренним...
И потом один и тот же модуль может иметь несколько инстансов - короче поиграл с лямбдами и макросами - вот такой трешак получился:

 TRASH

Code: Select all

#include "TRCMath.hpp"

using namespace std;

using namespace TRC;

#define CLASS(x) class x : public Entity { public: x(auto lambda){lambda(this);}
#define ENDCLASS }
#define ENTITY(x,y) x y([](auto u){u->name(#y)
#define ENDENTITY })
#define ATTACH(x) u->x = u->at

CLASS(MyUnit);

  // indecies:
  int i0,i1,i2;
  // inputs:
  Wire<8> net;
  // outputs:
  Signal sig;

  void step()
  {
    for(int i=0;i<8;i++)
      net[i] = io(i1+i).read();

    sig[0] = TRUE;

    if(posedge(i1+5))
    {

    }

    io(i0) << sig[0];
    io(i0+1) << sig[0];
    io(i2) << sig[0];
  }

ENDCLASS;


int main()
{
  Wire<5> a;
  Wire<32> b;
  Wire<1> signal,out;
  Signal signal2;
  Uint<32> u;
  Sint<32> s;
  s[0] = TRUE;
  b[31] = FALSE;
  a = TRUE; /* this is ok */
  u = TRUE; /* this must be wrong */
  s = b&&u;
  signal = MAYBE;
  signal2 = TRUE;
  out = signal & signal2;
  cout << "signal=" << signal << endl;
  cout << "signal2=" << signal2 << endl;
  cout << "out=" << out << endl;
  cout << "a=" << a << endl;
  cout << "b=" << b << endl;
  cout << "u=" << u << endl;
  cout << "s=" << s << endl;

  System *sys = System::getInstance();

  ENTITY(MyUnit,u1);
  ATTACH(i1)("bus",8,PULLUP);
  ATTACH(i1)("network",8);
  ATTACH(i2)("single");
  ENDENTITY;

  sys->clean();
  u1.step();
}

Наверное так делать ненадо...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Вот как надо:

Code: Select all

#include "TRCMath.hpp"

using namespace std;

using namespace TRC;

class MyUnit : public Entity
{
 protected:

  // indecies:
  int i0,i1,i2;
  // inputs:
  Wire<8> net;
  // outputs:
  Signal sig;

 public:

  MyUnit(const char* s) : Entity(s)
  {
    i0 = at("bus",8,PULLUP);
    i1 = at(".network",8);
    i2 = at("single");
  }

  void step()
  {
    for(int i=0;i<8;i++)
      net[i] = io(i1+i).read();

    sig[0] = TRUE;

    if(posedge(i1+5))
    {

    }

    io(i0) << sig[0];
    io(i0+1) << sig[0];
    io(i2) << sig[0];
  }
};


int main()
{
  Wire<5> a;
  Wire<32> b;
  Wire<1> signal,out;
  Signal signal2;
  Uint<32> u;
  Sint<32> s;
  s[0] = TRUE;
  b[31] = FALSE;
  s = b&&u;
  signal = MAYBE;
  signal2 = TRUE;
  out = signal & signal2;
  cout << "signal=" << signal << endl;
  cout << "signal2=" << signal2 << endl;
  cout << "out=" << out << endl;
  cout << "a=" << a << endl;
  cout << "b=" << b << endl;
  cout << "u=" << u << endl;
  cout << "s=" << s << endl;

  System *sys = System::getInstance();
  class Unit1 : public MyUnit
  {
   public:
    Unit1() : MyUnit("Unit1")
    {
      i2 = at("single2");
    }
  } u1;
  sys->clean();
  u1.step();
}
Если цепляемся к сигналу, имя которого начинается с точки, то к имени сигнала добавляется префикс имени модуля - таким образом можно заводить как бы локальные цепи и потом модули специфицируются в конструкторах дочерних классов - по одному конструктору на объект...
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 24080
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: TRCM - симулируем цифровое железо на C++

Post by Shaos »

Короче вот - придумал как внутренние объекты добавлять:

Code: Select all

#include "TRCMath.hpp"

using namespace std;

using namespace TRC;

class MyUnit : public Entity
{
 protected:

  // indecies:
  int i0,i1,i2;
  // inputs:
  Wire<8> net;
  // outputs:
  Signal sig;
  // internal objects:
  class InternalUnit : public Entity
  {
    public:

      int i1;

      InternalUnit(string s) : Entity(s.c_str())
      {
         i1 = at(".local");
      }

      void step()
      {

      }

  }*u1,*u2;

 public:

  MyUnit(const char* s) : Entity(s)
  {
    i0 = at("bus",8,PULLUP);
    i1 = at(".network",8);
    i2 = at("single");
    u1 = new InternalUnit(name("u1"));
    u2 = new InternalUnit(name("u2"));
  }

  void step()
  {
    for(int i=0;i<8;i++)
      net[i] = io(i1+i).read();

    sig[0] = TRUE;

    if(posedge(i1+5))
    {

    }

    io(i0) << sig[0];
    io(i0+1) << sig[0];
    io(i2) << sig[0];
  }
};


int main()
{
  Wire<5> a;
  Wire<32> b;
  Wire<1> signal,out;
  Signal signal2;
  Uint<32> u;
  Sint<32> s;
  s[0] = TRUE;
  b[31] = FALSE;
  s = b&&u;
  signal = MAYBE;
  signal2 = TRUE;
  out = signal & signal2;
  cout << "signal=" << signal << endl;
  cout << "signal2=" << signal2 << endl;
  cout << "out=" << out << endl;
  cout << "a=" << a << endl;
  cout << "b=" << b << endl;
  cout << "u=" << u << endl;
  cout << "s=" << s << endl;

  System *sys = System::getInstance();
  class Unit1 : public MyUnit
  {
   public:
    Unit1() : MyUnit("Unit1")
    {
      i2 = at("single2");
    }
  } u1;
  sys->prepare();
  u1.step();
}
Вышеприведённая программа печатает вот это:

Code: Select all

signal=O
signal2=P
out=O
a=ZZZZZ
b=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZN
u=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
s=????????????????????????????????
bus[0] <- Unit1
bus[1] <- Unit1
bus[2] <- Unit1
bus[3] <- Unit1
bus[4] <- Unit1
bus[5] <- Unit1
bus[6] <- Unit1
bus[7] <- Unit1
Unit1.network[0] <- Unit1
Unit1.network[1] <- Unit1
Unit1.network[2] <- Unit1
Unit1.network[3] <- Unit1
Unit1.network[4] <- Unit1
Unit1.network[5] <- Unit1
Unit1.network[6] <- Unit1
Unit1.network[7] <- Unit1
single <- Unit1
Unit1.u1.local <- Unit1.u1
Unit1.u2.local <- Unit1.u2
single2 <- Unit1
Я тут за главного - если что шлите мыло на me собака shaos точка net