번호판을 도단당하다.

지난 토요일에 아내가 미국에 갔습니다.
원정 출산은 아니고(28주밖에 안되었는데 무슨 원정출산이겠습니까..), 학회 때문에 갔는데, 걱정이 앞섭니다.
아내를 바라다 주고 와서, 차를 아파트 지하 주차장에 주차해놓았죠.
저야 출퇴근에 차를 사용하지 않으니까, 눈이라도 올까봐 실내가 좋겠다고 생각한 겁니다.

근데, 오늘 예전 회사 동료 결혼식에 차를 가지고 참석하려고 지하주차장에 갔는데, 분명 제가 차를 세워둔 자리에 제 차 비슷한 차가 있기는 한데 번호판이 없더군요.
황당했습니다. 번호판 가지고 간 사람이 좋은 목적으로 가져갔을리는 없고.. 불행중 다행으로 차에는 큰 문제가 없더군요..
아파트 경비 아저씨 불러서 차 번호판 도난 이야기하고, CCTV관련에서 여쭈어보고, 112에 신고한 이후에 관내 파출소에 가서 이런 저런 서류작성하고 관련 서류 받아서 왔습니다.
다음주면 아내가 귀국하기 때문에 차를 가져가야 하는데 참.. 큰일입니다.
다음주 월요일에 바로 자동차 등록소에 가서 새로 번호판을 발급받아야 겠군요.

뭔 무슨 도둑들이 뒷 번호판은 톱으로 나사를 잘라가버리다니.. -_-;
일단 차를 지상에 세워두긴했는데 영 찝찌름하군요.

경찰서에서는 혹시 국세를 체납한게 있냐고 하는데, 내가 뭐 그다지 국세를 낼 것도 없는 사람인지라…. 재산세니 뭐니는 벌써 다 냈으니까요.. 여하튼 월요일에(주말이라 관청들이 쉬는 관계로) 이런것 저런것 확인해준다네요..

에이.. 2007년의 마무리가 영~ 찝찌름합니다.

PLI에서 TCP/IP를 통해서 통신하고, perl server에서 처리하기

예전에 PLI에서 윈도우 제어 하려고 별짓을 다했었는데, 그 중에 PLI에서 TK 윈도우를 바로 부른 것도 있었습니다. PLI에서 TK를 부르는(C-TK interwork을 이용한) 방법은 TK 스크립을 거의 직접 쓸 수 있다는 점에서 편리하긴 한데, NCVerilog에서 너무 버전을 심하게 탄다는 단점(TK의 버전도 맞춰 줘야 합니다. -_-;)이 있어서 환경이 바뀌면서 잘 안쓰게 되더군요.

게다가 시뮬레이션 돌리면서 이런 저런것을 실시간 출력할때 UNIX/Linux/Windows 안가리는 인터페이스를 고민하다보니, TCP/IP와 Perl 만한게 없더군요. Simulator에서 이런 저런 GUI 부분이 귀찮아서 socket 기반으로 만들었던 기억을 되살려 하나 만들어봤습니다. PLI에서 TCP/IP 패킷을 전송하는 부분을 하나 만들어봤습니다.

#include 
#include <"arpa/inet.h">
#include <"net/netinet.h">
#include <"sys/socket.h">
#include <"sys/types.h"> #include "vpi_user.h"

#define DEST_IP "127.0.0.1"
#define DEST_PORT 7890

static struct sockaddr_in dest_addr;

static int count = 0;
static int sockfd;
int counta;

PLI_INT32 cosim_hello_calltf(PLI_BYTE8 *userdata) {
        char buf[1024];
        s_vpi_time ctime;
        ctime.type = vpiScaledRealTime;
        vpi_get_time(NULL, &ctime);
        vpi_printf("[%2.2f] Hello VPI: %d, %d\n", ctime.real, count, counta);
        sprintf(buf, "\n##[%2.2f] Hello VPI: %d, %d\n", ctime.real, count, counta);
        send(sockfd, &buf, sizeof(buf), 0);

        count++;
        counta++;
        return(0);
}

PLI_INT32 cosim_hello_init() {
        int len, result;
        counta = 100;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);

        dest_addr.sin_family = AF_INET;
        dest_addr.sin_port = htons(DEST_PORT);
        dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

        len = sizeof(dest_addr);
        result = connect(sockfd, (struct sockaddr *)&dest_addr, len);

        if (result == -1) {
                fprintf(stderr, "socket open error\n");
                exit(1);
        }

        return(0);
}

void cosim_register_hello() {
        s_vpi_systf_data tf_data;
        tf_data.type = vpiSysTask; // make as task
        tf_data.sysfunctype = 0;
        tf_data.tfname = "$cosim_hello";
        tf_data.calltf = cosim_hello_calltf;
        tf_data.compiletf = cosim_hello_init;
        tf_data.sizetf = NULL;
        tf_data.user_data = NULL;
        vpi_register_systf(&tf_data);
}

void (*vlog_startup_routines[])() = {cosim_register_hello, 0}


별 내용은 없고, 그냥 verilog code에서 cosim_hello()를 호출하면 loop돌면서 값을 출력하는 예제입니다.

 

이 코드 틀은 다이나릿의 기안도 박사님 IDEC 강좌 자료에 있는 “HW/SW 동시 협조 시뮬레이션”이란 강좌의 첫번째 PLI 예제에서 따왔으며, 저는 이 함수에 TCP/IP 전송이 가능하도록 수정하였습니다.

컴파일은 다음과 같이 일반적인 NCVerilog 컴파일과 다르지 않지요. (Windows에서 Modelsim 사용하시는 분은 gcc보다는 visual c++의 cl 을 사용하시는 것이 속 편합니다. MingW 버전의 gcc가 되기는 하는데, Modelsim에서 버전을 상당히 심하게 탔던 것으로 기억됩니다. 요즘 버전은 어떨지 모르겠습니다만. )

 

$gcc -I$CDS_HOME/tools/inca/include -c cosim_hello.c
$ld -shared -o cosim.so cosim_hello.o

NCVerilog Compile & Elaboration

 

$ ncvlog -work worklib test_hello.v
$ ncelab worklib.test_hello -loadvpi ./cosim:cosim_register_hello
$ ncsim worklib.test_hello


이런 식으로 사용하면 되는데, 위의 패킷을 받아줄 서버는 간단히 perl로 짜주면 됩니다. Perl-TK로 GUI를 작성하는 것도 가능하구요.

이때 한가지 주의해야 할 점은 perl의 IO::INET 의 accept() 함수가 blocking type이기 때문에 이것을 non-blocking type으로 해 주시고 loop을 돌려야지만 DoOneEvent() 함수가 정상적으로 수행된다는 점이지요.
(설마 MainLoop()로 돌리실 분은 없을 테니 ^^;) 저도 처음엔 DoOneEvent함수가 좀처럼 동작을 안하는 것처럼 느껴져서 헤맸습니다. 결론은 accept()함수 문제더군요.

perl 함수의 주요 부분만간단히 정리하자면(예제를 위해서 perl script를 하나 더 만들기가 귀찮고, 전체 내용은 회사 작업이라 공개할 수 없고.. 라는 어려움 때문에 별로 문제 안되는 부분만 올립니다. )



use strict;
use IO::Socket;
use Tk;
use encoding 'utf-8';    # 한글 쓰시려면..
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

my $portnum = 7890;

# make a socket

my $mw = MainWindow->new(-title=>"Terminal");

.....

my $sock = IO::Socket::INET->new(
                LocalHost => 'localhost',
                LocalPort => $portnum,
                Proto => 'tcp',
                Listen => 10, # SOMAXCONN 으로 해도 됩니다.
                Reuse => 1,
                TimeOut => 1,
                );

....
my($new_sock, $c_addr, $buf, $flag);
...

# NonBlocking으로 만듭시다.
$flag = fcntl($sock, F_GETFL, 0) or die "Can not get flag: $!\n";
$flag = fcntl($sock, F_SETFL, $flag | O_NONBLOCK) or die "Can not set flag: $!\n";

while(1) {
        while (($new_sock, $c_addr) = $sock->accept()) {
                ... 소켓에서 읽어서 일하세요....
                        DoOneEvent(0);
        }

 

요런 식이라는 것이지요. 중간 중간에 엄청 생략되어 있음은 유의하세요..

28주 3일

이번에는 입체 초음파를 찍었습니다. 지난번에 갔을때 입체 초음파를 하겠다고 하길래 냉큼 한다고 했지요. 사실 돈을 더 내더라도 매번 입체 초음파를 하고 싶은 마음입니다만.. 그게 이런 저런 절차들 때문에 맘대로 되지는 않는군요.
이번에는 얼굴을 볼 수 있다고 해서, 상당히 기대하고 갔었습니다. 그런데, 하필이면 애기가 자고 있는 시간이었던데다가 얼굴과 발을 모두 얼굴있는 곳에 두고 자고 있어서 얼굴 보기가 쉽지 않았습니다.

 

 

 

그래도, 손을 움직이게 해서 얼굴을 찍을 수는 있었지요.
아직 자세를 바꾸지 않은 상태라 약간 걱정되기는 합니다만, 32주까지는 움직일 수 있다니 기다려 봐야겠습니다.