nedoPC.org

Community of electronics hobbyists established in 2002

...
Atom Feed | View unanswered posts | View active topics It is currently 18 Dec 2018 06:38



Reply to topic  [ 30 posts ]  Go to page 1, 2  Next
TRCM - симулируем цифровое железо на C++ 
Author Message
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Нечто сподвигло меня вчера засесть за современный C++ и начать под лицензией GPLv3 писать систему симуляции, которая в перспективе могла бы быть пригодна служить в качестве HDL на замену всех этих ваших Вэрилогов :roll:

https://gitlab.com/ternary/trcm

Прожэкт на Хакадее: https://hackaday.io/project/160393-trcm

_________________
:eugeek: https://twitter.com/Shaos1973


12 Aug 2018 20:53
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Короче - до этого момента я всегда все свои симуляшные движки писал отталкиваясь от идеи, что у нас есть входы и есть выходы, но в реальности всё не так - источники напряжений могут подключаться и отключаться от проводников (двунаправленные сигналы) - тот же FPGA например невозможно сэмулировать не имея возможности переподключаться то так, то эдак. Вобщем я решил идти от уже проверенных промышленных подходов (добавив немного своего троичного) - на проводник могут накладываться вот такие значения:
Code:
 // 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)

_________________
:eugeek: https://twitter.com/Shaos1973


12 Aug 2018 21:05
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Пример играния с шинами (C++ имеет возможность шаблонить классы цифрами):
Code:
#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:
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. Можно попробовать написать конвертер из верилога в такое представление на сях++, чтобы погонять существующие большие мягкие процы...

_________________
:eugeek: https://twitter.com/Shaos1973


12 Aug 2018 21:07
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 09:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
Вобщем я решил идти от уже проверенных промышленных подходов (добавив немного своего троичного) - на проводник могут накладываться вот такие значения:
Code:
 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


13 Aug 2018 08:07
Profile
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Ну таки хаки, только без них FPGA не сымитируешь ;)

P.S. Заменил X на ? и переименовал run() в step()

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 09:08
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 09:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
Ну таки хаки, только без них FPGA не сымитируешь ;)

Без них ты и троичную логику не сымитируешь ;) Но ты ведь так упирался! :roll:
http://www.nedopc.org/forum/viewtopic.php?p=140444#p140444

Кстати, " ? " , на мой взгляд, будет сбивать с толку. Лучше подбери подходящую букву.

_________________
iLavr


13 Aug 2018 09:20
Profile
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Lavr wrote:
Shaos wrote:
Ну таки хаки, только без них FPGA не сымитируешь ;)

Без них ты и троичную логику не сымитируешь ;) Но ты ведь так упирался! :roll:
http://www.nedopc.org/forum/viewtopic.php?p=140444#p140444

Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 09:24
Profile WWW
Supreme God
User avatar

Joined: 21 Oct 2009 09:08
Posts: 7777
Location: Россия
Reply with quote
Shaos wrote:
Lavr wrote:
Без них ты и троичную логику не сымитируешь ;)
Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)

Железно ли, бетОнно ли, но одними лог. "0" и "1" - не обойтись. :lol:
Придётся так или иначе вводить лог. "1/2" , несмотря на то, что "входы есть входы, выходы есть выходы".

О чем, тебе, собственно, и говорили: http://www.nedopc.org/forum/viewtopic.php?p=140424#p140424

_________________
iLavr


13 Aug 2018 09:31
Profile
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Lavr wrote:
Shaos wrote:
Lavr wrote:
Без них ты и троичную логику не сымитируешь ;)
Ну если там всё железобетнно - входы есть входы, выходы есть выходы, то вполне можно и сымитировать :)

Железно ли, бетОнно ли, но одними лог. "0" и "1" - не обойтись. :lol:
Придётся так или иначе вводить лог. "1/2" , несмотря на то, что "входы есть входы, выходы есть выходы".

Да я собственно свой DDT имел ввиду - там только 3 значения N,O,P и никаких «грязных хаков» :)
Ну и плюс X при задании таблиц истинности...

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 10:23
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
По существу есть претензии? Вопросы?

Я вот думаю что наверное надо спрятать от юзера чтение снаружи и запись вовне - скажем неявно это делать для железобетонных входов и железобетонных выходов (а такие точно будут).
А "входовыходы" менять по ходу работы (подключая их то как вход, то как выход, то как отключено) плюс наверное надо завести понятие "выход с Z состоянием", а также входы подтянутые к земле или к питанию.
Специальные OK выходы наверное заводить не стоит, хотя что такое OK? Это выход который может либо отключаться либо подключаться к земле, а на той стороне стоит подтяжка к питанию - так что это можно сымитировать уже имеющимися средствами...

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 19:45
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Shaos wrote:
Я вот думаю что наверное надо спрятать от юзера чтение снаружи и запись вовне - скажем неявно это делать для железобетонных входов и железобетонных выходов (а такие точно будут).

С другой стороны когда всё навиду, то всё прозрачно, вот так например можно Z-состояние делать:
Code:
if(enabled)
  io(network1)<<store;
else
  io(network1)<<NC;

И входы можно читать не все всегда, а только те, которые нужны в текущем состоянии и т.д.

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 20:21
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Lavr wrote:
Кстати, " ? " , на мой взгляд, будет сбивать с толку. Лучше подбери подходящую букву.

Ну 0 и 1 тоже уже не буквы :)

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 20:30
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Есть момент, о котором я забыл - надо сделать так, чтобы было достаточно просто добавлять вложенные модули как члены класса!
Вложенный модуль не будет иметь доступ к внешним цепям, но будет иметь доступ ко внутренним...
И потом один и тот же модуль может иметь несколько инстансов - короче поиграл с лямбдами и макросами - вот такой трешак получился:
 TRASH
Code:
#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();
}
Наверное так делать ненадо...

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 23:35
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Вот как надо:
Code:
#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();
}

Если цепляемся к сигналу, имя которого начинается с точки, то к имени сигнала добавляется префикс имени модуля - таким образом можно заводить как бы локальные цепи и потом модули специфицируются в конструкторах дочерних классов - по одному конструктору на объект...

_________________
:eugeek: https://twitter.com/Shaos1973


13 Aug 2018 23:54
Profile WWW
Admin
User avatar

Joined: 09 Jan 2003 00:22
Posts: 17236
Location: Colorado
Reply with quote
Короче вот - придумал как внутренние объекты добавлять:
Code:
#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:
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

_________________
:eugeek: https://twitter.com/Shaos1973


14 Aug 2018 22:01
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 30 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.